package it.poste.il.compensatore.control.impl;

import it.poste.il.compensatore.cancellations.interf.ICancellation;
import it.poste.il.compensatore.control.Integration;
import it.poste.il.compensatore.entities.Message;
import it.poste.il.compensatore.entities.MessageBody;
import it.poste.il.compensatore.entities.SDPRequest;
import it.poste.il.compensatore.exceptions.CompensatorIOException;
import it.poste.il.compensatore.exceptions.CompensatorTimeOutException;
import it.poste.il.compensatore.service.DataManagerService;
import it.poste.il.compensatore.service.impl.DataManagerServiceImpl;
import it.poste.il.compensatore.utilities.Constant;
import it.poste.il.compensatore.utilities.Constant.DEF_VERIFY_RESULT;
import it.poste.il.compensatore.utilities.LoggerCompensatore;
import it.poste.il.compensatore.utilities.SendSOAPMessage;

import java.sql.Date;

public class IntegrationImpl implements Integration {
	
	private int timeout = 1000;
	
	private static IntegrationImpl instance;

	private static LoggerCompensatore loggerF;
	
	public LoggerCompensatore getLoggerF() {
		return loggerF;
	}

	public void setLoggerF(LoggerCompensatore loggerF) {
		this.loggerF = loggerF;
	}
	

	private IntegrationImpl() {
		super();
		init();		
	}
	
	private void init(){
		Constant.init();
	}
	
	public static IntegrationImpl getInstance() {
		if(instance==null){
			instance = new IntegrationImpl();
		}
		return instance;
	}
	
	/**
	 * Method syncMsg.
	 * Read input message, load requestID, store message
	 * check annullament and reset
	 * send to ESB.
	 * @param input message from SDP
	 * @return ESB reply ;
	 * @throws Exception 
	 */
	public String syncMsg(String msg) throws Exception {
				
		DataManagerService dataManagerService=new DataManagerServiceImpl();
		String response = null;
		LoggerCompensatore logger=(LoggerCompensatore)loggerF.getLogger(this);
		MessageBody messageBody = new MessageBody();
		Message message = new Message();
		int fromAccountingDate = 0;
		int fromBranch = 8;
		int fromWorkingStationId = 13;
		int fromNumberOperationPdl = 17;
		int fromCounter = 23;
		String fase = "";
		//load requestId header
	
		logger.info("START PARSER");
		int startRequestID = msg.indexOf("requestID>");
		int endRequestID = msg.substring(startRequestID+10).indexOf("</");
		String requestId = msg.substring(startRequestID+10).substring(0,endRequestID);
		System.out.println("Request ID: " + requestId);
		logger.info("END PARSER");
		
		//load requestId
		SDPRequest sdpRequest = new SDPRequest();
		logger.info("request id: " + requestId);

		sdpRequest.setAccountingDate(requestId.subSequence(fromAccountingDate, fromBranch).toString());
		logger.info(sdpRequest.getAccountingDate());
		sdpRequest.setBranch(requestId.substring(fromBranch, fromWorkingStationId));
		logger.info(sdpRequest.getBranch());
		sdpRequest.setWorkingStationId(Integer.parseInt(requestId.substring(fromWorkingStationId, fromNumberOperationPdl)));
		logger.info((""+sdpRequest.getWorkingStationId()));
		sdpRequest.setNumberOperationPdl(Integer.parseInt(requestId.substring(fromNumberOperationPdl, fromCounter)));
		logger.info(""+sdpRequest.getNumberOperationPdl());
		sdpRequest.setCounter(Integer.parseInt(requestId.substring(fromCounter, requestId.length()-1)));
		logger.info(""+sdpRequest.getCounter());
		fase=requestId.substring(requestId.length()-1);
		logger.info(fase);
		
		
		logger.info("request id: avccountingdate: " + sdpRequest.getAccountingDate() + " branch: " + sdpRequest.getBranch() + 
				" workingstation: " + sdpRequest.getWorkingStationId() + " counter: " + sdpRequest.getCounter() +
				" pdl: " + sdpRequest.getNumberOperationPdl());
		
		//memo
		logger.info("memorizza request");
		messageBody = dataManagerService.storeMsg(msg,sdpRequest);
		message = messageBody.getMessage();
		
		DEF_VERIFY_RESULT check = dataManagerService.verifyRequest(message.getSdpRequestId(), fase);
		logger.info("check " + check);
		
		//check
		if(check==DEF_VERIFY_RESULT.RIALLIGN){
			logger.info("check = 3 reset");
			reset(sdpRequest);
		} else if(check==DEF_VERIFY_RESULT.CANCEL){
//			dataManagerService.changeStatus(message, Constant.WAITING_RESPONSE_ERROR);
			logger.info("check cancellation");
			//check have message id 
			cancel(check.getVerifyCode());
		}
		try{
			dataManagerService.changeStatus(message, Constant.AWAITING_RESPONSE);
			response = send(messageBody);
			dataManagerService.changeStatus(message, Constant.PERFORMED);
		} catch (CompensatorTimeOutException e) {
			logger.info("send avoid message for timeout");
			dataManagerService.changeStatus(message, Constant.WAITING_RESPONSE_ERROR);
			cancel(messageBody.getMessage().getSdpRequestId().getId().toString());
		} catch (CompensatorIOException e){
			logger.error("Error send http request to ESB " + e);
			dataManagerService.changeStatus(message, Constant.TECHNICAL_ERROR);
			throw e;
		} catch (Exception e) {
			logger.error("Generic error " + e);
			dataManagerService.changeStatus(message, Constant.TECHNICAL_ERROR);
			throw e;
		}
		return response;
		
	}

	/**
	 * Method explicitCancel.
	 * Make annullament message.
	 * @return null;
	 */
	public void explicitCancel(Message message){
		LoggerCompensatore logger=(LoggerCompensatore)loggerF.getLogger(this);
		logger.debug(" Method explicitCancel");
		
		logger.debug("START PARSER explicitCancel");
		String msg = message.getMessageBodys().getInputMessage().toString();
		int startOperationNumber = msg.indexOf("numeroOperazione>");
		int endOperationNumber = msg.substring(startOperationNumber+1).indexOf("</");
		String operation = msg.substring(startOperationNumber+10).substring(0,endOperationNumber);
		logger.debug("operation number: " + operation);
		logger.debug("END PARSER explicitCancel");
		
		
		ICancellation ncanc=(ICancellation) Constant.avoid.get(message.getOperationId().getObjHelper());
		
		String sendingMessage = ncanc.sendSoap("soapAction", 100, message.getOperationId().getUrlAvoidEndpoint(), "source", "requestID", 
				"routingRole", "creationTime", message.getSdpRequestId().getBranch(), 
				message.getSdpRequestId().getAccountingDate(), 
				 Integer.toString(message.getSdpRequestId().getWorkingStationId()),
				operation);
		
		
	}
	
	/**
	 * Method annullament.
	 * Make annullament message.
	 * @return null;
	 */
	public void cancel(String sdpRequestId){
		DataManagerService dataManagerService=new DataManagerServiceImpl();
		LoggerCompensatore logger=(LoggerCompensatore)loggerF.getLogger(this);
		Message avoidMessage = new Message();
		logger.debug(" Method annullament");
	}
	
	/**
	 * Method reset.
	 * Make reset .
	 * @return null;
	 */
	public void reset(SDPRequest sdpRequest) {
		DataManagerService dataManagerService=new DataManagerServiceImpl();
		LoggerCompensatore logger=(LoggerCompensatore)loggerF.getLogger("Riallign");
		logger.insertCancellation("Allineamento requestId - accountigdate: " + sdpRequest.getAccountingDate() 
				+ " workingStatioID: " + sdpRequest.getWorkingStationId() + " counter:" +sdpRequest.getCounter());
		logger.debug("reset all counter :" + sdpRequest.getCounter() + " for accountigdate "+
				sdpRequest.getAccountingDate() + " branch " + sdpRequest.getBranch() + " PDL " + sdpRequest.getNumberOperationPdl() +
				" workingStationId " + sdpRequest.getWorkingStationId());
	}
	
	/**
	 * Method send.
	 * Send message to ESB and return error message.
	 * @return response;
	 * @throws CompensatorTimeOutException 
	 * @throws CompensatorIOException 
	 */
	public String send(MessageBody msgBody) throws CompensatorTimeOutException, CompensatorIOException,Exception{
		SendSOAPMessage sendSOAPMessage=new SendSOAPMessage();
		LoggerCompensatore logger=(LoggerCompensatore)loggerF.getLogger(this);
		logger.debug("start send");
		String URL = msgBody.getMessage().getOperationId().getUrlEndpoint();
		logger.debug("URL "+ URL);
		String action = msgBody.getMessage().getOperationId().getOperationName();
		logger.debug("OperationName " + action);
		String msg = msgBody.getInputMessage();
		logger.debug("msg ");
		
		
		String result="";
		try {
			logger.info("send request to ESB");			
			result = sendSOAPMessage.sendStringRequest(msg, URL, action, timeout);
		} catch (CompensatorTimeOutException e) {
			//Change status "Error..."
			logger.error("Timeout exception");
			throw e;
		} catch (CompensatorIOException e) {
			logger.error("IO Exception");
			throw e;
		} catch (Exception e) {
			logger.error("Generic error");
			throw e;
		}
		
		return result;
	}

	

}
 